package com.goldsprite.gameframeworks.ecs;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

public class LayerMask {
	private static final List<String> layers = new CopyOnWriteArrayList<>();
	private static final Map<String, Integer> layerIndices = new ConcurrentHashMap<>();
	private static final int MAX_LAYERS = 16;//这里为了适配box2D最高16
	private static final BitSet[] collisionMatrix = new BitSet[MAX_LAYERS];
	private static int nextAvailableIndex = 0;

	public static synchronized int createLayer(String layerName) {
		if (layerIndices.containsKey(layerName)) {
			return layerIndices.get(layerName);
		}

		if (nextAvailableIndex >= MAX_LAYERS) {
			throw new IllegalStateException("已达到最大层数限制: " + MAX_LAYERS);
		}

		int index = nextAvailableIndex++;
		while (index < layers.size() && layers.get(index) != null) {
			index++;
		}

		if (index < layers.size()) {
			layers.set(index, layerName);
		} else {
			layers.add(layerName);
		}

		layerIndices.put(layerName, index);
		collisionMatrix[index] = new BitSet(MAX_LAYERS);

//		// 默认与自己碰撞
//		collisionMatrix[index].set(index, true);

		return index;
	}

	public static synchronized void deleteLayer(String layerName) {
		Integer index = layerIndices.get(layerName);
		if (index != null) {
			layers.set(index, "[Deleted]" + layerName);
			layerIndices.remove(layerName);
			collisionMatrix[index] = null;

			// 从所有碰撞矩阵中移除该层
			for (int i = 0; i < MAX_LAYERS; i++) {
				if (collisionMatrix[i] != null) {
					collisionMatrix[i].clear(index);
				}
			}
		}
	}

	public static void setLayerCollision(String selfLayerName, String... maskLayerNames) {
		for (String maskLayerName : maskLayerNames) {
			setLayerCollision(selfLayerName, maskLayerName, true);
		}
	}
	public static void setLayerCollision(String layerA, String layerB, boolean canCollide) {
		int indexA = getLayerIndex(layerA);
		int indexB = getLayerIndex(layerB);

		if (collisionMatrix[indexA] != null) {
			collisionMatrix[indexA].set(indexB, canCollide);
		}
		if (collisionMatrix[indexB] != null) {
			collisionMatrix[indexB].set(indexA, canCollide);
		}
	}

	public static void setLayerCollision(int layerA, int layerB, boolean canCollide) {
		if (layerA >= 0 && layerA < MAX_LAYERS && collisionMatrix[layerA] != null) {
			collisionMatrix[layerA].set(layerB, canCollide);
		}
		if (layerB >= 0 && layerB < MAX_LAYERS && collisionMatrix[layerB] != null) {
			collisionMatrix[layerB].set(layerA, canCollide);
		}
	}

	/**
	 * 设置该层与所有已存在的层碰撞
	 */
	public static void setLayerCollisionAll(String layerName) {
		int layerIndex = getLayerIndex(layerName);
		if (collisionMatrix[layerIndex] == null) return;

		// 设置与所有已注册层碰撞
		for (String otherLayer : getAllLayers()) {
			int otherIndex = getLayerIndex(otherLayer);
			collisionMatrix[layerIndex].set(otherIndex, true);
		}
	}

	/**
	 * 设置该层与所有层碰撞（包括未来可能添加的层）
	 */
	public static void setLayerCollisionAllAlways(String layerName) {
		int layerIndex = getLayerIndex(layerName);
		if (collisionMatrix[layerIndex] == null) return;

		// 设置与所有可能的层碰撞（0到MAX_LAYERS-1）
		collisionMatrix[layerIndex].set(0, MAX_LAYERS);
		for(BitSet set : collisionMatrix) {
			if (set != null)
				set.set(layerIndex);
		}
		;
	}

	public static boolean canLayersCollide(String layerA, String layerB) {
		int indexA = getLayerIndex(layerA);
		int indexB = getLayerIndex(layerB);
		return canLayersCollide(indexA, indexB);
	}

	public static boolean canLayersCollide(int layerA, int layerB) {
		if (layerA < 0 || layerA >= MAX_LAYERS || layerB < 0 || layerB >= MAX_LAYERS) {
			return false;
		}

		return collisionMatrix[layerA] != null &&
			collisionMatrix[layerB] != null &&
			collisionMatrix[layerA].get(layerB);
	}

	public static int getLayerIndex(String layerName) {
		Integer index = layerIndices.get(layerName);
		if (index == null) {
			throw new IllegalArgumentException("未知的层名称: " + layerName);
		}
		return index;
	}

	public static String getLayerName(int index) {
		if (index >= 0 && index < layers.size()) {
			String name = layers.get(index);
			return name.startsWith("[Deleted]") ? "Invalid" : name;
		}
		return "Unknown";
	}

	public static List<String> getAllLayers() {
		List<String> activeLayers = new ArrayList<>();
		for (String layer : layers) {
			if (layer != null && !layer.startsWith("[Deleted]")) {
				activeLayers.add(layer);
			}
		}
		return activeLayers;
	}

	public static int getLayerCount() {
		return layerIndices.size();
	}

	public static int nameToLayer(String layerName) {
		Integer index = layerIndices.get(layerName);
		return index != null ? index : -1;
	}

	public static BitSet getLayerMask(String... layerNames) {
		BitSet mask = new BitSet(MAX_LAYERS);
		for (String layerName : layerNames) {
			int index = nameToLayer(layerName);
			if (index != -1) {
				mask.set(index);
			}
		}
		return mask;
	}

	public static boolean isInLayerMask(int layer, BitSet layerMask) {
		return layerMask.get(layer);
	}

	public static void debugLayers() {
		System.out.println("=== LayerMask Debug Info ===");
		System.out.println("Total Layers: " + getLayerCount());
		System.out.println("Max Layers: " + MAX_LAYERS);

		List<String> allLayers = getAllLayers();
		for (String layer : allLayers) {
			int index = getLayerIndex(layer);
			System.out.println("Layer '" + layer + "' (Index: " + index + ")");
		}
	}

	// 将层名称转换为Box2D需要的category bits (short)
	public static short nameToCategoryBits(String layerName) {
		int layerIndex = nameToLayer(layerName);
		if (layerIndex == -1) return 0;
		return (short) (1 << layerIndex);
	}

	// 将BitSet掩码转换为Box2D需要的mask bits (short)
	public static short bitSetToMaskBits(BitSet bitSet) {
		if (bitSet == null) return 0;

		short mask = 0;
		// 使用nextSetBit只遍历设置的位，而不是所有位
		for (int i = bitSet.nextSetBit(0); i >= 0 && i < MAX_LAYERS; i = bitSet.nextSetBit(i + 1)) {
			mask |= (short) (1 << i);
		}
		return mask;
	}

	// 根据层名称获取对应的碰撞掩码(short)
	public static short getMaskBitsForLayer(String layerName) {
		int layerIndex = nameToLayer(layerName);
		if (layerIndex == -1) return 0;

		BitSet collisionMask = collisionMatrix[layerIndex];
		return bitSetToMaskBits(collisionMask);
	}

	// 便捷方法：一次性获取category和mask
	public static short[] getCategoryAndMask(String layerName) {
		short category = nameToCategoryBits(layerName);
		short mask = getMaskBitsForLayer(layerName);
		return new short[]{category, mask};
	}

	// 从short mask bits转换回BitSet（用于调试）
	public static BitSet maskBitsToBitSet(short maskBits) {
		BitSet bitSet = new BitSet(MAX_LAYERS);
		for (int i = 0; i < 16; i++) {
			if ((maskBits & (1 << i)) != 0) {
				bitSet.set(i);
			}
		}
		return bitSet;
	}

	// 增强的调试方法，显示Box2D格式
	public static void debugLayersWithBox2DInfo() {
		System.out.println("=== LayerMask with Box2D Info (One-way) ===");
		System.out.println("Total Layers: " + getLayerCount());

		List<String> allLayers = getAllLayers();
		for (String layer : allLayers) {
			int index = getLayerIndex(layer);
			short category = nameToCategoryBits(layer);
			short mask = getMaskBitsForLayer(layer);

			System.out.printf("Layer '%s' (Index: %d)\n", layer, index);
			System.out.printf("  Box2D: category=0x%04X, mask=0x%04X\n",
				category & 0xFFFF, mask & 0xFFFF);

			// 显示这个层可以碰撞哪些层
			BitSet collisions = collisionMatrix[index];
			if (collisions != null) {
				System.out.print("  Can collide with: ");
				boolean hasCollisions = false;
				for (int i = 0; i < MAX_LAYERS; i++) {
					if (collisions.get(i)) {
						System.out.print(getLayerName(i) + " ");
						hasCollisions = true;
					}
				}
				if (!hasCollisions) {
					System.out.print("NOTHING");
				}
				System.out.println();
			}
			System.out.println();
		}
	}
}
